package com.primeton.whdc.ccms.reportimpl.service.impl;

import com.baomidou.mybatisplus.core.metadata.IPage;
import com.primeton.whdc.ccms.reportimpl.dao.ApiCallRecordDAO;
import com.primeton.whdc.ccms.reportimpl.entity.CallRecord;
import com.primeton.whdc.ccms.reportimpl.mapper.CallRecordMapper;
import com.primeton.whdc.ccms.reportimpl.mqueue.consumer.KafkaReceiver;
import com.primeton.whdc.ccms.reportimpl.param.ApiVO;
import com.primeton.whdc.ccms.reportimpl.param.ReportRecordTreeVO;
import com.primeton.whdc.ccms.reportimpl.param.ReportRecordVO;
import com.primeton.whdc.ccms.reportimpl.service.IApiCallRecordService;
import com.primeton.whdc.ccms.reportimpl.service.ILoginService;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.AntPathMatcher;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @author: YunTao.Li
 * @create: 2020-04-10 21:57
 * @description:
 **/
@Service
public class ApiCallRecordServiceImpl implements IApiCallRecordService {

    private Logger logger = LoggerFactory.getLogger(ApiCallRecordServiceImpl.class);

    @Resource
    private CallRecordMapper callRecordMapper;

    @Autowired
    private ApiCallRecordDAO apiCallRecordDAO;

    @Autowired
    private ILoginService loginService;

    /**
     * 分页查询api调用记录
     *
     * @param condition :
     * @return : com.baomidou.mybatisplus.core.metadata.IPage<com.primeton.whdc.ccms.reportimpl.entity.CallRecord>
     * @author : YunTao.Li
     * @date : 2020/4/2 2020/4/2
     */
    @Override
    public IPage<CallRecord> getAPICallRecordList(Map<String, Object> condition) throws Throwable {
        IPage<CallRecord> applicationIPage = this.apiCallRecordDAO.getCallRecordList(condition);
        return applicationIPage;
    }

    /**
     * 新增api调用记录
     *
     * @param record :
     * @return : com.sun.javafx.collections.MappingChange.Map<java.lang.String,java.lang.String>
     * @author : YunTao.Li
     * @date : 2020/4/25 2020/4/25
     */
    @Override
    public Map<String, String> addAPICallRecord(CallRecord record) throws Throwable {
        Map<String, String> result = new HashMap<String, String>();
        result.put("code", "-1");

        try {
            String confUser = record.getCofUname();
            String path = record.getPath();
            String method = record.getMethod();

            if (("GET").equals(method) || isPathSikp(path)) {
                logger.info("the method {0} or path {1} is not allowed to save", method, path);
                result.put("code", "1");
                return result;
            }

            // step1 : 根据confUser实际上就是userid查询员工信息
            Map<String, String> empInfo = loginService.getEmpInfoByCofUser(confUser);
            String empCode = empInfo.get("empCode");
            String empName = empInfo.get("empName");
            String appId = empInfo.get("appId");
            String orgCode = empInfo.get("orgCode");
            String deptCode = empInfo.get("deptCode");
            String orgName = empInfo.get("orgName");
            String deptName = empInfo.get("deptName");

            record.setEmpCode(empCode);
            record.setEmpName(empName);
            record.setOrgCode(orgCode);
            record.setOrgName(orgName);
            record.setDeptCode(deptCode);
            record.setDeptName(deptName);

            /**
             * step2 查询出所有的API列表 TODO:这里应该从缓存拿
             * 并针对url进行匹配
             *
             * */
            List<ApiVO> apiInfos = apiCallRecordDAO.selectApiInfos();

            AntPathMatcher antPathMatcher = new AntPathMatcher();
            for (int i = 0; i < apiInfos.size(); i++) {
                ApiVO api = apiInfos.get(i);
                String pattern = api.getPath();

                String newPattern = "";
                // step2.1 : 将/{xxx}匹配全部换成 / *
                for (String pattern_char : pattern.split("/")) {
                    if (pattern_char.startsWith("{") && pattern_char.endsWith("}")) {
                        pattern_char = "*";
                    }
                    newPattern += "/" + pattern_char;
                }
                newPattern = newPattern.replace("//", "/");
                if (antPathMatcher.match(newPattern, path)) {
                    record.setApiName(api.getApidesc());
                    record.setAppName(api.getAppname());
                    break;
                } else {
                    newPattern = "/ccms" + newPattern;
                    if (antPathMatcher.match(newPattern, path)) {
                        record.setApiName(api.getApidesc());
                        record.setAppName(api.getAppname());
                        break;
                    }
                }
            }

//            // step2 : 根据path查询app与syscode信息 TODO:这里以后需要从缓存取，不然太耗性能了
//            // step2.1 : 去掉/ccms开头
//
//
//            List<ApiVO> infoList = apiCallRecordDAO.selectApiInfoREGEXPPath(method, path);
//
//            if (infoList.size() > 0) {
//                ApiVO info = infoList.get(0);
//                String apiName = info.getApidesc();
//                String appName = info.getAppname();
//
//                record.setApiName(apiName);
//                record.setAppName(appName);
//            }

            // step3 : 保存数据
            String apiName = record.getApiName();
            boolean isSkip = KafkaReceiver.skip(apiName);
            System.out.println("save data with apiName = " + apiName + "skip:" + isSkip);
            if (isSkip || StringUtils.isBlank(apiName)) {
                // do nothing
            } else {
                this.callRecordMapper.insert(record);
            }

        } catch (Throwable e) {
            e.printStackTrace();
            throw e;
        }

        result.put("code", "1");
        return result;
    }

    /**
     * 查询周报月报
     *
     * @param condition :
     * @return : java.util.List<com.primeton.whdc.ccms.reportimpl.param.ReportRecordVO>
     * @author : YunTao.Li
     * @date : 2020/8/17 2020/8/17
     */
    @Override
    public List<ReportRecordTreeVO> getReport(Map<String, Object> condition) throws Throwable {
        List<ReportRecordVO> reportRecords = new ArrayList();
        List<ReportRecordTreeVO> reportRecordTree = new ArrayList();
        String range = (String) condition.get("queryRange");

        if (("person").equals(range)) {
            condition.put("deptCode", null);
        }

        String qtype = (String) condition.get("qtype");
        if (("month").equals(qtype)) {
            reportRecords.addAll(this.apiCallRecordDAO.getMonthReport(condition));
        } else if (("week").equals(qtype)) {
            reportRecords.addAll(this.apiCallRecordDAO.getWeekReport(condition));
        }

        Map appNamecontainsKey = new HashMap();
        List<ReportRecordVO> tmpReportRecords = new ArrayList();
        ReportRecordTreeVO treeVo = new ReportRecordTreeVO();
        for (int i = 0; i < reportRecords.size(); i++) {
            ReportRecordVO reportRecord = reportRecords.get(i);
            String appName = reportRecord.getAppName();

            if (appNamecontainsKey.containsKey(appName)) {
                treeVo.getRecord().add(reportRecord);
            } else {
                treeVo = new ReportRecordTreeVO();
                tmpReportRecords = new ArrayList();
                tmpReportRecords.add(reportRecord);
                treeVo.setRecord(tmpReportRecords);
                treeVo.setAppName(appName);
                appNamecontainsKey.put(appName, 1);
                reportRecordTree.add(treeVo);
            }
        }

        return reportRecordTree;
    }

    /**
     * 需要跳过的path，目前暂时先指定几个
     *
     * @param path :
     * @return : java.lang.Boolean
     * @author : YunTao.Li
     * @date : 2020/4/8 2020/4/8
     */
    protected Boolean isPathSikp(String path) {
        boolean f = false;
        //TODO:
        if (("/coframe/api/users/login").equals(path)) {
            f = true;
        }
        return f;
    }


}
